#ifndef __SCENE_H_
#define __SCENE_H_

#include <vector>
#include "point.h"
#include <set>
#include <functional>
#include <memory>
#include <map>

typedef struct _Node
{
	_Node(int val, const std::shared_ptr<_Node>& pare, const Point* _self)
	:f_val(val), parent(pare), self(_self)
	{}
	int				f_val;
	std::shared_ptr<_Node>	parent;
	const Point*	self;
}Node, *PNode;

class Scene final
{
public:
	Scene(int width, int height);
	~Scene()
	{
        set_cursor(0, m_height + 1);
        ::show_cursor();
	}
	Scene(const Scene&) = delete;
	Scene& operator= (const Scene&) = delete;

    void draw(int x, int y, unsigned int color);
	
	void test1()
	{
		for (int i = 5; i <= 40; ++i)
		{
			m_map[20][i].pass = false;
			draw(20, i, BLUE);
		}
	}

	void test2()
	{
		for (int i = 5; i <= 25; ++i)
		{
			m_map[20][i].pass = false;
			draw(20, i, BLUE);
		}

		for (int i = 25; i <= 40; ++i)
		{
			m_map[30][i].pass = false;
			draw(30, i, BLUE);
		}
	}

	void find(Point const& start, Point const& end);
	
private:
	void showback(std::shared_ptr<Node> const& node);
	void AddNewOpenList(std::shared_ptr<Node> const&, Point const&, int);
	void find(const std::shared_ptr<_Node>&, Point const& end);
	inline bool CheckPoint(Point const& point)
	{
		if (point.pass && !m_closeList[point.x][point.y])
		{
			return true;
		}
		return false;
	}
private:
	int CalcG(Point const& p1, Point const& p2)
	{
		auto ret = abs(p1.x - p2.x) + abs(p1.y - p2.y);
		if (ret == 1)
		{
			return 10;
		}
		else if (ret == 2)
		{
			return 14;
		}
		else
		{
			return -1;	
		}
	}

	unsigned int CalcH(Point const& start, Point const& end)
	{
		return (abs(end.x - start.x) + abs(end.y - start.y)) * 5;
	}
private:
	std::vector<std::vector<Point>>	m_map;
	std::vector<std::vector<bool>>	m_closeList;
	std::set<std::shared_ptr<Node>, std::function<bool(std::shared_ptr<Node> const&, std::shared_ptr<Node> const&)>> m_openList;
    int     m_height;
};

#endif
